﻿using System;
using System.Diagnostics;
using System.Net;
using System.Threading;
using Misuzilla.Net.Irc;

namespace Misuzilla.Crigate.Handler
{
    [ParentAppDomain]
    [ActivateContext(ActivateContexts.SessionInitialized)]
    public class BasicHandler : MarshalByRefObject,
                                IHandler,
                                IMessageHandler,
                                IMessageHandler<UserMessage>,
                                IMessageHandler<NickMessage>,
                                IMessageHandler<PassMessage>,
                                IMessageHandler<QuitMessage>,
                                IMessageHandler<PingMessage>,
                                IMessagePreSendHandler<NumericReplyMessage>
    
    {
        private Session CurrentSession { get; set; }

        #region IHandler メンバ
        public void Initialize(Session session)
        {
            CurrentSession = session;
        }

        public void Uninitialize()
        {
        }
        #endregion

        #region IDisposable メンバ
        public void Dispose()
        {
        }
        #endregion
        
        private void StartSession()
        {
            // USER/NICK がそろったら開始
            if (!CurrentSession.IsStarted && !String.IsNullOrEmpty(CurrentSession.User.Nick) && !String.IsNullOrEmpty(CurrentSession.User.UserName))
            {
                if (CurrentSession.Authenticate())
                {
                    Type t = typeof(Server);
                    CurrentSession.User.ClientHost = String.Format("{0}!{1}@{2}", CurrentSession.User.Nick,
                                                                   CurrentSession.User.UserName,
                                                                   ((IPEndPoint)(((IrcSession)CurrentSession).TcpClient.Client.RemoteEndPoint)).Address);
                    CurrentSession.SendNumericReply(NumericReply.RPL_WELCOME,
                                                    String.Format("Welcome to the Internet Relay Network {0}",
                                                                  CurrentSession.User.ClientHost));
                    CurrentSession.SendNumericReply(NumericReply.RPL_YOURHOST,
                                                    String.Format("Your host is {0}, running version {1}", t.FullName,
                                                                  t.Assembly.GetName().Version));
                    CurrentSession.SendNumericReply(NumericReply.RPL_CREATED,
                                                    String.Format("This server was created {0}", DateTime.Now));
                    CurrentSession.SendNumericReply(NumericReply.RPL_MYINFO,
                                                    String.Format("{0} {1}-{2} {3} {4}", Environment.MachineName,
                                                                  t.FullName, t.Assembly.GetName().Version, "", ""));

                    CurrentSession.OnSessionStarted(CurrentSession.User.UserName);
                    Trace.WriteLine(String.Format("SessionStarted: {0}", CurrentSession.User.ToString()));
                }
                else
                {
                    Thread.Sleep(10 * 1000);
                    CurrentSession.Close();
                }
            }

        }

        #region IMessageHandler<TIrcMessage>
        public bool OnMessageReceived(PassMessage ircMessage)
        {
            CurrentSession.User.Password = ircMessage.Content;
            return true;
        }

        public bool OnMessageReceived(NickMessage ircMessage)
        {
            CurrentSession.User.Nick = ircMessage.NewNick;
            StartSession();
            return true;
        }

        public bool OnMessageReceived(UserMessage ircMessage)
        {
            CurrentSession.User.UserName = ircMessage.User;
            StartSession();
            return true;
        }

        public bool OnMessageReceived(QuitMessage ircMessage)
        {
            try
            {
                CurrentSession.Close();
            }
            catch { }

            return true;
        }

        public bool OnMessageReceived(PingMessage ircMessage)
        {
            CurrentSession.Send(new PongMessage(ircMessage.Receiver));
            return true;
        }
        #endregion

        #region Implementation of IMessageHandler<IrcMessage>

        public bool OnMessageReceived(IrcMessage ircMessage)
        {
            System.Console.WriteLine(ircMessage.ToString());
            return true;
        }

        #endregion

        #region ISendMessageHandler<NumericReplyMessage> メンバ

        public bool OnPreMessageSend(NumericReplyMessage ircMessage)
        {
            System.Console.WriteLine("Send: " + ircMessage.ToString());
            return true;
        }

        #endregion
    }
}
